
;	-------------------------------------------------------
;	ADAPTATION OF VTI TO USE SOLID STATE MUSIC VIDEO BOARD 
;	MODEL VB1-B WITH F-80 I-O ROUTINES ON UAP'S IMSAI 8080.
;		[VERSION JANUARY 27,1979]
;
;		VB1-B  -  COPYRIGHT (C) 1979
;		UNIVERSIDAD AUTONOMA DE PUEBLA
;
;	WRITTEN BY HAROLD V. MCINTOSH, SUMMER 1978, WITH
;	REFERENCE TO: HARVEY A. COHEN, "THE OZNAKI LIFE",
;	DR. DOBBS JOURNAL OF COMPUTER CALISTHENICS AND
;	ORTHODONTIA, VOLUME 3, ISSUE 4 (APRIL 1978) PP. 10-11;
;	AND WITH ACKNOWLEDGEMENTS TO THE HOSPITALITY OF THE
;	QUANTUM THEORY PROJECT, UNIVERSITY OF FLORIDA,
;	GAINESVILLE, FLORIDA.
;	------------------------------------------------------

;	-------------------------------------------------------
;	CONSTANTS DEFINING SCREEN SIZE AND LOCATION.  NOTE THAT
;	WHILE THE PROGRAMMER HAS SOME DISCRETION IN ASSIGNING
;	THESE CONSTANTS, THERE IS HIGHLY IMPLICIT USAGE OF THE
;	ASSUMPTION THAT THE SCREEN MEMORY BEGINS AT A 1K HEX
;	BOUNDARY, AND THAT THE ROW LENGTH IS A POWER OF 2.
;	THUS THE VIDEO BOARD ORIGIN MAY BE CHANGED THROUGH ITS
;	ADDRESS SWITCHES, AND NEW PARAMETERS DEFINED WITHOUT
;	DIFFICULTY; NEVERTHELESS ADAPTATION TO AN 80-COLUMN 
;	BOARD WOULD REQUIRE RESTRUCTURING THE SUBROUTINES.
;	-------------------------------------------------------

VORG	EQU	0F800H	;ORIGIN OF VIDEO SCREEN MEMORY AREA
VSIZ	EQU	00400H	;SIZE OF VIDEO SCREEN MEMORY AREA
RSIZ	EQU	00040H	;LENGTH OF A SINGLE DISPLAY LINE
RMSK	EQU	0003FH	;MASK FOR SINGLE ROW ADDRESSES

;	-------------------------------------------------------
;	DATA STORAGE LOCATIONS REQUIRED BY THE SUBROUTINES.
;	-------------------------------------------------------

	DSEG

MA:	DB	00	;BIT MASK TO LOCATE PIXEL WITHIN BYTE
WY:	DB	00	;ROW COUNT * 16  -  16 ROWS TOTAL
EX:	DB	00	;COLUMN COUNT * 4  -  64 COLUMNS TOTAL
TS:	DB	00	;TEMPORARY STORAGE

;	=======================================================

	CSEG

;	MOVE CURSOR UP ONE PIXEL

YPL::	LXI	H,MA
	MOV	A,M
	ANI	009H
	JNZ	YP1
	MOV	A,M
	RRC
	MOV	M,A
	RET
YP1:	RLC
	RLC
	MOV	M,A
	LDA	WY
	SUI	010H
	STA	WY
	RET

;	MOVE CURSOR DOWN ONE PIXEL

YMI::	LXI	H,MA
	MOV	A,M
	ANI	024H
	JNZ	YM1
	MOV	A,M
	RLC
	MOV	M,A
	RET
YM1:	RRC
	RRC
	MOV	M,A
	LDA	WY
	ADI	010H
	STA	WY
	RET

;	MOVE CURSOR RIGHT ONE PIXEL

XPL::	LXI	H,MA
	MOV	A,M
	ANI	038H
	JNZ	XP1
	MOV	A,M
	RLC
	RLC
	RLC
	MOV	M,A
	RET
XP1:	RRC
	RRC
	RRC
	MOV	M,A
	LDA	EX
	ADI	004H
	STA	EX
	RET

;	MOVECURSOR LEFT ONE PIXEL

XMI::	LXI	H,MA
	MOV	A,M
	ANI	007H
	JNZ	XM1
	MOV	A,M
	RRC
	RRC
	RRC
	MOV	M,A
	RET
XM1:	RLC
	RLC
	RLC
	MOV	M,A
	LDA	EX
	SUI	004H
	STA	EX
	RET

;	FAST MOVEMENT OF CURSOR RIGHT TWO PIXELS

XPPL::	LDA	EX
	ADI	004H
	STA	EX
	RET

;	FAST MOVEMENT OF CURSOR LEFT TWO PIXELS

XMMI::	LDA	EX
	SUI	004H
	STA	EX
	RET

;	LOAD A WITH THE BIT MASK, HL WITH A BYTE ADDRESS
;	GIVEN THE CURSOR POSITIONING DATA AT (MA,WY,EX)

DOT:	LHLD	WY
	MOV	A,H
	MVI	H,VORG/0400H
	DAD	H
	DAD	H
	RRC
	RRC
	ORA	L
	MOV	L,A
	LDA	MA
	RET

;	INITIALIZE CURSOR PARAMETERS

HOME::	LXI	H,8080H
	SHLD	WY
	MVI	A,001H
	STA	MA
	RET

;	EXTINGUISH THE CURSOR

CUEX::	CALL	DOT
	ORA	M
	MOV	M,A
	RET

;	LIGHT THE CURSOR

CULI::	CALL	DOT
	CMA
	ANA	M
	MOV	M,A
	RET

;	REVERSE THE CURSOR

CURE::	CALL	DOT
	XRA	M
	MOV	M,A
	RET

;	SENSE THE CURSOR

CUSE::	CALL	DOT
	ANA	M
	ANI	03FH
	RET

;	CLEAR THE WHOLE SCREEN TO BLACK

BLAK::	LXI	D,VSIZ
	LXI	H,VORG
BL1:	MVI	M,0FFH
	INX	H
	DCR	E
	JNZ	BL1
	DCR	D
	JNZ	BL1
	RET

;	CLEAR THE WHOLE SCREEN TO WHITE

WHIT::	LXI	D,VSIZ
	LXI	H,VORG
WHI:	MVI	M,080H
	INX	H
	DCR	E
	JNZ	WHI
	DCR	D
	JNZ	WHI
	RET

;	REVERSE THE WHOLE SCREEN

REVE::	LXI	D,VSIZ
	LXI	H,VORG
REV1:	MOV	A,M
	XRI	03FH
	MOV	M,A
	INX	H
	DCR	E
	JNZ	REV1
	DCR	D
	JNZ	REV1
	RET

;	TRANSFORM CARTESIAN COORDINATES IN THE FORM OF X,Y
;	TRANSMITTED THROUGH REGISTERS (D,E) TO A MASK AND
;	BYTE ADDRESS.

CART::	PUSH	D
	MOV	D,M
	POP	H
	MOV	E,M
KART::	MVI	B,018H
	MVI	C,004H
	MOV	A,E
	CMA
	ADI	031H
CAR1:	CMP	B
	JC	CAR2
	SUB	B
CAR2:	CMC
	ADC	A
	DCR	C
	JNZ	CAR1
	MOV	C,A
	ANI	00FH
	RLC
	RLC
	RLC
	RLC
	STA	WY
	MOV	A,C
	ANI	0F0H
	JNZ	CAR3
	MVI	A,008H
CAR3:	MOV	C,A
	MOV	A,D
	DCR	A
	MOV	B,A
	RLC
	ANI	0FCH
	STA	EX
	MOV	A,B
	ANI	001H
	MOV	A,C
	JNZ	CAR4
	RRC
	RRC
	RRC
CAR4:	STA	MA
	RET

;	DRAW A LINE WITH INCREMENTS DX,DY = (D,E).  INCREMENT
;	MAY BE + OR - USING COMPLEMENTARY ARITHMETIC, BUT OUGHT
;	TO BE LESS THAN 64 IN ABSOLUTE VALUE TO AVOID OVERFLOW
;	PROBLEMS.

LINE::	LXI	H,YPL
	MOV	A,E
	ORA	A
	JP	LIN1
	CMA
	INR	A
	MOV	E,A
	LXI	H,YMI
LIN1:	LXI	B,XPPL
	MOV	A,D
	ORA	A
	JP	LIN2
	CMA
	INR	A
	MOV	D,A
	LXI	B,XMMI
LIN2:	CMP	E
	JNC	LIN3
	PUSH	H
	PUSH	B
	POP	H
	POP	B
	MOV	D,E
	MOV	E,A
LIN3:	MOV	A,D
	STA	TS
	MOV	A,E
	ADD	A
	MOV	E,A
	SUB	D
	PUSH	PSW
	SUB	D
	MOV	D,A
LIN4:	POP	PSW
	PUSH	H
	LXI	H,DOLI
	XTHL
	CPI	001H
	JM	LIN5
	PUSH	H
	ADD	D
	JMP	LIN6
LIN5:	ADD	E
LIN6:	PUSH	B
	PUSH	PSW
	LDA TS
	DCR A
	STA TS
	JNZ LIN4
	POP PSW
	RET

;	THE MOVEMENTS IN ONE BYTE NECESSARY TO SHIFT THE
;	WHOLE SCREEN RIGHT ONE PIXEL.

EXPL:	MOV	A,M
	ANI	03FH
	MOV	B,A
	ANI	007H
	RLC
	RLC
	RLC
	ORA	C
	MOV	C,A
	MOV	A,B
	RRC
	RRC
	RRC
	ANI	007H
	MOV	B,C
	MOV	C,A
	RET

;	THE MOVEMENTS WITHIN ONE BYTE NECESSARY FOR SHIFTING
;	THE WHOLE SCREEN LEFT ONE PIXEL.

EXMI:	MOV	A,M
	ANI	03FH
	MOV	B,A
	RRC
	RRC
	RRC
	ANI	007H
	ORA	C
	MOV	C,A
	MOV	A,B
	ANI	007H
	RLC
	RLC
	RLC
	MOV	B,C
	MOV	C,A
	RET

;	THE MOVEMENTS NECESSARY WITHIN ONE BYTE TO SHIFT THE
;	WHOLE SCREEN DOWN ONE PIXEL.

WYMI:	MOV	A,M
	ANI	03FH
	MOV	B,A
	ANI	01BH
	RLC
	ORA	C
	MOV	C,A
	MOV	A,B
	RRC
	RRC
	ANI	009H
	MOV	B,C
	MOV	C,A
	RET

;	THE MOVEMENTS NECESSARY WITHIN ONE BYTE TO SHIFT THE
;	WHOLE SCREEN UP ONE PIXEL.

WYPL:	MOV	A,M
	ANI	03FH
	MOV	B,A
	RRC
	ANI	01BH
	ORA	C
	MOV	C,A
	MOV	A,B
	ANI	009H
	RLC
	RLC
	MOV	B,C
	MOV	C,A
	RET

;	ROTATE THE WHOLE SCREEN RIGHT ONE PIXEL

EKSPL::	LXI	H,VORG
	LXI	D,RSIZ-1
EKSP1:	PUSH	H
	DAD	D
	CALL	EXPL
	POP	H
EKSP2:	CALL	EXPL
	MOV	A,B
	ORI	080H
	MOV	M,A
	INX	H
	MOV	A,L
	ANI	LOW(RMSK)
	JNZ	EKSP2
	MOV	A,H
	CPI	HIGH(VORG+VSIZ)
	JNZ	EKSP1
	RET

;	ROTATE THE WHOLE SCREEN LEFT ONE PIXEL

EKSMI::	LXI	H,VORG+VSIZ-1
	LXI	D,-RSIZ+1
EKSM1:	PUSH	H
	DAD	D
	CALL	EXMI
	POP	H
EKSM2:	CALL	EXMI
	MOV	A,B
	ORI	080H
	MOV	M,A
	MOV	A,L
	ANI	LOW(RMSK)
	DCX	H
	JNZ	EKSM2
	MOV	A,H
	CPI	HIGH(VORG)-1
	JNZ	EKSM1
	RET

;	ROTATE THE WHOLE SCREEN UP ONE PIXEL.

WYEPL::	LXI	H,VORG+VSIZ-1
WYEP1:	LXI	D,-VSIZ+RSIZ
	PUSH	H
	DAD	D
	CALL	WYPL
	POP	H
	PUSH	H
	LXI	D,-RSIZ
WYEP2:	CALL	WYPL
	MOV	A,B
	ORI	080H
	MOV	M,A
	DAD	D
	MOV	A,H
	CPI	HIGH(VORG)-1
	JNZ	WYEP2
	POP	H
	MOV	A,L
	ANI	LOW(RMSK)
	DCX	H
	JNZ	WYEP1
	RET

;	ROTATE THE WHOLE SCREEN DOWN ONE PIXEL

WYEMI::	LXI	H,VORG
WYEM1:	LXI	D,VSIZ-RSIZ
	PUSH	H
	DAD	D
	CALL	WYMI
	POP	H
	PUSH	H
	LXI	D,RSIZ
WYEM2:	CALL	WYMI
	MOV	A,B
	ORI	080H
	MOV	M,A
	DAD	D
	MOV	A,H
	CPI	HIGH(VORG+VSIZ)
	JNZ	WYEM2
	POP	H
	INX	H
	MOV	A,L
	ANI	LOW(RMSK)
	JNZ	WYEM1
	RET

;	FAST RIGHT ROTATION BY TWO PIXELS = ONE BYTE

EKSPPL::	LXI	H,VORG
	LXI	D,RSIZ-1
EKSPP1:	PUSH	H
	DAD	D
	MOV	C,M
	POP	H
EKSPP2:	MOV	B,M
	MOV	M,C
	MOV	C,B
	INX	H
	MOV	A,L
	ANI	LOW(RMSK)
	JNZ	EKSPP2
	MOV	A,H
	CPI	HIGH(VORG+VSIZ)
	JNZ	EKSPP1
	RET

;	FAST LEFT ROTATE BY TWO PIXELS = ONE BYTE

EKSMMI::	LXI	H,VORG+VSIZ-1
	LXI	D,-RSIZ+1
EKSMM1:	PUSH	H
	DAD	D
	MOV	C,M
	POP	H
EKSMM2:	MOV	B,M
	MOV	M,C
	MOV	C,B
	MOV	A,L
	ANI	LOW(RMSK)
	DCX	H
	JNZ	EKSMM2
	MOV	A,H
	CPI	HIGH(VORG)-1
	JNZ	EKSMM1
	RET

;	ADD TO THE NEIGHBOR COUNT OF ADJOINING CELLS ACCORDING
;	TO THE BITS IN THIS BYTE.  WE DO THE MIDDLE PIXEL,
;	ADDING TO THE COUNT OF THREE SUCCESSIVE NEIGHBORS IN
;	REGISTERS B,C,D.

ALFA:	MOV	A,M
	RLC
	RLC
	RLC
	JC	ALF1
	INR	B
	INR	C
	INR	D
ALF1:	RLC
	JC	ALF2
	INR	B
	INR	D
ALF2:	RLC
	RC
	INR	B
	INR	C
	INR	D
	RET

;	SHIFT THE NEIGHBOR COUNT AS WE MOVE FORWARD ONE BYTE IN
;	A ROW SCAN

BETA:	MOV	B,C
	MOV	C,D
	MVI	D,00H
	INX	H
	MOV	A,L
	ANI	03FH
	RNZ
	PUSH	D
	LXI	D,-RSIZ
	DAD	D
	POP	D
	RET

;	PRINCIPAL PROGRAM FOR CARRYING OUT A CYCLE OF LIFE.
;	ONLY THE MIDDLE PIXEL IN EACH BYTE IS CALCULATED
;	SO THAT THREE PASSES ARE NECESSARY AFTER EACH OF THREE
;	SHIFTS. TWO ADJACENT PIXELS ARE USED, THE RIGHT TO HOLD
;	THE PRESENT LIVING STATUS AND THE LEFT FOR INFORMATION
;	FOR THE NEXT CYCLE.

EPSI:	LXI	H,VORG+RSIZ-1
GAMA:	MVI	D,00H
	CALL	ALFA
	CALL	BETA
	CALL	ALFA
DELT:	PUSH	H
	CALL	BETA
	CALL	ALFA
	XTHL
	MOV	A,B
	CPI	002H
	JZ	ETA
	CPI	003H
	JZ	ZETA
	MOV	A,M
	ORI	002H
	MOV	M,A
	JMP	THET
ZETA:	MOV	A,M
	ANI	0FDH
	MOV	M,A
	JMP	THET
ETA:	MOV	A,M
	ANI	0FDH
	MOV	E,A
	ANI	010H
	RRC
	RRC
	RRC
	ORA	E
	MOV	M,A
THET:	POP	H
	MOV	A,L
	ANI	LOW(RMSK)
	JNZ	DELT
	PUSH	D
	LXI	D,2*RSIZ-1
	DAD	D
	POP	D
	MOV	A,H
	CPI	HIGH(VORG+VSIZ)
	JNZ	GAMA
	RET

;	UPDATING LOOP, MOVING LEFT PIXEL TO RIGHT

CYCL:	LXI	H,VORG
CYC1:	MOV	A,M
	ANI	007H
	MOV	B,A
	RLC
	RLC
	RLC
	ORA	B
	ORI	080H
	MOV	M,A
	INX	H
	MOV	A,H
	CPI	HIGH(VORG+VSIZ)
	JNZ	CYC1
	RET

;	EXECUTE A SINGLE CYCLE OF LIFE BY UPDATING THE MIDDLE
;	PIXEL AND MAKING THREE SWEEPS WHILE SHIFTING EACH TIME

HH::	CALL	EPSI
	CALL	WYEPL
	CALL	EPSI
	CALL	WYEPL
	CALL	EPSI
	CALL	WYEMI
	CALL	WYEMI
	JMP	CYCL

;	EXTINGUISH CURSOR, MOVE TWO PIXELS EAST, LIGHT CURSOR

EE::	CALL	CURE
	CALL	XPPL
	JMP	 CURE

;	EXTINGUISH CURSOR, TWO PIXELS WEST, LIGHT CURSOR

WW::	CALL	CURE
	CALL	XMMI
	JMP	 CURE

;	EXTINGUISH CURSOR, ONE PIXEL NORTH, LIGHT CURSOR

NN::	CALL	CURE
	CALL	YPL
	JMP	CURE

;	EXTINGUISH CURSOR, ONE PIXEL SOUTH, LIGHT CURSOR

SS::	CALL	CURE
	CALL	YMI
	JMP	CURE

;	EXTINGUISH A LIFE CELL

KK::	CALL	XPL
	CALL	CUEX
	JMP	XMI

;	ACTIVATE A LIFE CELL

LL::	CALL	XPL
	CALL	CULI
	JMP	XMI

;	MOVE WHOLE SCREEN RIGHT ONE LIFE CELL, WITH CURSOR

EAS::	CALL	EKSPPL
	JMP	XPPL

;	MOVE THE WHOLE SCREEN LEFT ONE LIFE CELL, WITH CURSOR

WES::	CALL	EKSMMI
	JMP	 XMMI

;	MOVE THE WHOLE SCREEN UP ONE LIFE CELL, WITH CURSOR

NOR::	CALL	WYEPL
	JMP	 YPL

;	MOVE THE WHOLE SCREEN DOWN ONE LIFE CELL, WITH CURSOR

SOU::	CALL	WYEMI
	JMP	 YMI

;	LIGHT A TWO-PIXEL DOT

DOLI::	CALL	CULI
	CALL	XPL
	CALL	CULI
	JMP	XMI

;	EXTINGUISH A TWO-PIXEL DOT

DOEX::	CALL	CUEX
	CALL	XPL
	CALL	CUEX
	JMP	XMI

	END
